package com.weaving.monitor.service;

import com.weaving.monitor.dto.ProdTodayAmountExportDto;
import com.weaving.monitor.entity.ProdProdCardProcess;
import com.weaving.monitor.entity.ProdTodayAmount;
import com.weaving.monitor.entity.SysUser;
import com.weaving.monitor.mapper.FactoryMachineSpeedMapper;
import com.weaving.monitor.mapper.ProdFlawMapper;
import com.weaving.monitor.mapper.ProdProdCardMapper;
import com.weaving.monitor.mapper.ProdProdCardProcessMapper;
import com.weaving.monitor.mapper.ProdTodayAmountMapper;
import com.weaving.monitor.mapper.SysUserMapper;
import com.weaving.monitor.util.FlawTypeUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 生产今日产量导出服务
 * 
 * 功能说明：
 * 1. 查询prod_today_amount表数据
 * 2. 关联查询用户信息和工艺参数
 * 3. 从Redis获取车速信息
 * 4. 生成Excel报表
 * 
 * @author 系统开发团队
 * @version 1.0
 * @since 2024-01-01
 */
@Service
public class ProdTodayAmountExportService {
    
    @Autowired
    private ProdTodayAmountMapper prodTodayAmountMapper;
    
    @Autowired
    private SysUserMapper sysUserMapper;
    
    @Autowired
    private ProdProdCardProcessMapper prodProdCardProcessMapper;
    
    @Autowired
    private ProdProdCardMapper prodProdCardMapper;
    
    @Autowired
    private ProdFlawMapper prodFlawMapper;
    
    @Autowired
    private FactoryMachineSpeedMapper factoryMachineSpeedMapper;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 根据日期范围查询导出数据
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 导出数据列表
     */
    public List<ProdTodayAmountExportDto> getExportData(LocalDate startDate, LocalDate endDate) {
        try {
            System.out.println("开始查询生产数据，日期范围：" + startDate + " 到 " + endDate);
            
            // 1. 查询生产数据
            List<ProdTodayAmount> productionData = prodTodayAmountMapper.selectByDateRange(startDate, endDate);
            System.out.println("查询到原始数据条数：" + productionData.size());
            
            if (productionData.isEmpty()) {
                System.out.println("没有查询到生产数据");
                return new ArrayList<>();
            }
            
            // 1.1 过滤数据：每个cardId只保留subClothSeq最大的记录
            // 首先找到每个cardId对应的最大subClothSeq值
            Map<String, Integer> maxSubClothSeqMap = productionData.stream()
                    .filter(item -> item.getSubClothSeq() != null)
                    .collect(Collectors.groupingBy(
                            ProdTodayAmount::getCardId,
                            Collectors.mapping(
                                    ProdTodayAmount::getSubClothSeq,
                                    Collectors.maxBy(Integer::compareTo)
                            )
                    ))
                    .entrySet().stream()
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            entry -> entry.getValue().orElse(0)
                    ));
            
            // 然后过滤出每个cardId中subClothSeq等于最大值的所有记录
            List<ProdTodayAmount> filteredProductionData = productionData.stream()
                    .filter(item -> {
                        String cardId = item.getCardId();
                        Integer maxSubClothSeq = maxSubClothSeqMap.get(cardId);
                        if (maxSubClothSeq == null) {
                            // 如果该cardId没有有效的subClothSeq，保留原记录
                            return true;
                        }
                        // 保留subClothSeq等于最大值的记录
                        return item.getSubClothSeq() != null && item.getSubClothSeq().equals(maxSubClothSeq);
                    })
                    .collect(Collectors.toList());
            
            System.out.println("过滤后数据条数：" + filteredProductionData.size());
        
        // 2. 获取所有用户ID和卡号，用于批量查询
        Set<String> userIds = filteredProductionData.stream()
                .map(ProdTodayAmount::getUserId)
                .collect(Collectors.toSet());
        System.out.println("需要查询的用户ID数量：" + userIds.size() + ", 用户ID列表：" + userIds);
        
        Set<String> cardIds = filteredProductionData.stream()
                .map(ProdTodayAmount::getCardId)
                .collect(Collectors.toSet());
        System.out.println("需要查询的卡号数量：" + cardIds.size() + ", 卡号列表：" + cardIds);
        
        // 3. 批量查询用户信息
        Map<String, String> userMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            try {
                List<SysUser> users = sysUserMapper.selectByIds(new ArrayList<>(userIds));
                System.out.println("查询到用户信息条数：" + users.size());
                userMap = users.stream()
                        .collect(Collectors.toMap(SysUser::getId, SysUser::getUsername));
            } catch (Exception e) {
                System.err.println("查询用户信息失败：" + e.getMessage());
                e.printStackTrace();
            }
        }
        
        // 4. 批量查询工艺参数
        Map<String, BigDecimal> densityMap = new HashMap<>();
        if (!cardIds.isEmpty()) {
            try {
                List<ProdProdCardProcess> processes = prodProdCardProcessMapper.selectByCardIds(new ArrayList<>(cardIds));
                System.out.println("查询到工艺参数条数：" + processes.size());
                densityMap = processes.stream()
                        .collect(Collectors.toMap(ProdProdCardProcess::getCardId, ProdProdCardProcess::getStitchDensity));
            } catch (Exception e) {
                System.err.println("查询工艺参数失败：" + e.getMessage());
                e.printStackTrace();
            }
        }
        
        // 5. 构建导出数据
        List<ProdTodayAmountExportDto> exportData = new ArrayList<>();
        System.out.println("开始构建导出数据...");
        
        for (ProdTodayAmount data : filteredProductionData) {
            try {
                ProdTodayAmountExportDto dto = new ProdTodayAmountExportDto();
                
                // 设置基本信息
                dto.setDate(data.getCreateTime().toLocalDate());
                dto.setMachineId(data.getMachineId());
                
                // 获取真实的物料名称
                String materialName = prodProdCardMapper.selectMaterialNameByCardId(data.getCardId());
                if (materialName != null && !materialName.trim().isEmpty()) {
                    dto.setProductName(materialName);
                } else {
                    dto.setProductName("坯布" + data.getCardId()); // 如果查询不到物料名称，使用默认格式
                }
                
                dto.setSubClothSeq(data.getSubClothSeq());
                dto.setAmount(data.getAmount());

                // 根据产品ID查询疵点类型并设置质量状态
                String qualityStatus = FlawTypeUtil.getFlawTypesStringByProductId(data.getProdId(), prodFlawMapper);
                dto.setQualityStatus(qualityStatus);
                
                // 设置工人姓名
                String workerName = userMap.get(data.getUserId());
                dto.setWorkerName(workerName != null ? workerName : data.getUserId());
                
                // 设置上班时间和下班时间
                dto.setStartTime(data.getCreateTime()); // 上班时间取create_time
                dto.setUpdateTime(data.getUpdateTime());   // 下班时间取update_time
                
                // 设置密度
                BigDecimal density = densityMap.get(data.getCardId());
                dto.setDensity(density != null ? density : new BigDecimal("0.00"));
                
                // 根据产品的上班时间和下班时间查询平均车速
                Integer averageSpeed = 0; // 默认车速
                try {
                    LocalDateTime startTime = data.getCreateTime(); // 上班时间
                    LocalDateTime endTime = data.getUpdateTime() == null ? LocalDateTime.now() : data.getUpdateTime();    // 下班时间
                    
                    if (startTime != null && endTime != null) {
                        Double avgSpeed = factoryMachineSpeedMapper.selectAverageSpeedByMachineIdAndTimeRange(
                                data.getMachineId(), startTime, endTime);
                        
                        if (avgSpeed != null) {
                            averageSpeed = (int) Math.round(avgSpeed);
                            System.out.println("产品 " + data.getProdId() + " 机台 " + data.getMachineId() + 
                                             " 平均车速：" + averageSpeed);
                        } else {
                            System.out.println("产品 " + data.getProdId() + " 机台 " + data.getMachineId() + 
                                             " 没有车速数据，使用默认车速：0");
                        }
                    } else {
                        System.out.println("产品 " + data.getProdId() + " 上班时间或下班时间为空，使用默认车速：0");
                    }
                } catch (Exception e) {
                    System.err.println("查询产品 " + data.getProdId() + " 车速失败：" + e.getMessage());
                    e.printStackTrace();
                }
                
                dto.setSpeed(averageSpeed);
                
                exportData.add(dto);
            } catch (Exception e) {
                System.err.println("处理数据记录失败：" + e.getMessage());
                e.printStackTrace();
            }
        }
        
        System.out.println("成功构建导出数据条数：" + exportData.size());
        
        // 按照日期正序排序
        exportData.sort((a, b) -> a.getDate().compareTo(b.getDate()));
        System.out.println("数据已按日期正序排序");
        
        return exportData;
        
        } catch (Exception e) {
            System.err.println("查询导出数据失败：" + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }
    
    /**
     * 生成Excel报表
     * @param data 导出数据
     * @return Excel文件字节数组
     */
    public byte[] generateExcelReport(List<ProdTodayAmountExportDto> data) {
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet("生产今日产量报表");
            
            // 创建标题行样式
            CellStyle headerStyle = workbook.createCellStyle();
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerFont.setColor(IndexedColors.WHITE.getIndex()); // 设置表头字体颜色为白色
            headerStyle.setFont(headerFont);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
            headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            headerStyle.setBorderTop(BorderStyle.THIN);
            headerStyle.setBorderBottom(BorderStyle.THIN);
            headerStyle.setBorderLeft(BorderStyle.THIN);
            headerStyle.setBorderRight(BorderStyle.THIN);
            
            // 创建数据行样式
            CellStyle dataStyle = workbook.createCellStyle();
             dataStyle.setAlignment(HorizontalAlignment.CENTER);
            dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            dataStyle.setBorderTop(BorderStyle.THIN);
            dataStyle.setBorderBottom(BorderStyle.THIN);
            dataStyle.setBorderLeft(BorderStyle.THIN);
            dataStyle.setBorderRight(BorderStyle.THIN);
            
            // 创建标题行
            Row headerRow = sheet.createRow(0);
            String[] headers = {"日期", "机台号", "品名", "分幅数", "工人", "上班时间", "下班时间", "班次产量", "车速", "密度", "质量状态"};
            
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerStyle);
                sheet.setColumnWidth(i, 15 * 256); // 设置列宽
            }
            
            // 创建数据行
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            for (int i = 0; i < data.size(); i++) {
                ProdTodayAmountExportDto dto = data.get(i);
                Row row = sheet.createRow(i + 1);
                
                // 日期
                Cell dateCell = row.createCell(0);
                dateCell.setCellValue(dto.getDate().format(dateFormatter));
                dateCell.setCellStyle(dataStyle);
                
                // 机台号
                Cell machineCell = row.createCell(1);
                machineCell.setCellValue(dto.getMachineId());
                machineCell.setCellStyle(dataStyle);
                
                // 品名
                Cell productCell = row.createCell(2);
                productCell.setCellValue(dto.getProductName());
                productCell.setCellStyle(dataStyle);
                
                // 分幅数
                Cell subClothCell = row.createCell(3);
                subClothCell.setCellValue(dto.getSubClothSeq());
                subClothCell.setCellStyle(dataStyle);
                
                // 工人
                Cell workerCell = row.createCell(4);
                workerCell.setCellValue(dto.getWorkerName());
                workerCell.setCellStyle(dataStyle);
                
                // 上班时间
                Cell startTimeCell = row.createCell(5);
                if (dto.getStartTime() != null) {
                    startTimeCell.setCellValue(dto.getStartTime().format(timeFormatter));
                } else {
                    startTimeCell.setCellValue("");
                }
                startTimeCell.setCellStyle(dataStyle);
                
                // 下班时间
                Cell endTimeCell = row.createCell(6);
                if (dto.getUpdateTime() != null) {
                    endTimeCell.setCellValue(dto.getUpdateTime().format(timeFormatter));
                } else {
                    endTimeCell.setCellValue("");
                }
                endTimeCell.setCellStyle(dataStyle);
                
                // 班次产量
                Cell amountCell = row.createCell(7);
                amountCell.setCellValue(dto.getAmount());
                amountCell.setCellStyle(dataStyle);
                
                // 车速
                Cell speedCell = row.createCell(8);
                speedCell.setCellValue(dto.getSpeed());
                speedCell.setCellStyle(dataStyle);
                
                // 密度
                Cell densityCell = row.createCell(9);
                densityCell.setCellValue(dto.getDensity().doubleValue());
                densityCell.setCellStyle(dataStyle);
                
                // 质量状态
                Cell qualityCell = row.createCell(10);
                qualityCell.setCellValue(dto.getQualityStatus());
                qualityCell.setCellStyle(dataStyle);
            }
            
            // 输出到字节数组
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);
            return outputStream.toByteArray();
            
        } catch (Exception e) {
            throw new RuntimeException("生成Excel报表失败", e);
        }
    }
}
